// ============================================================================
// 日志服务
// ============================================================================

import { createLogger, logger, Logger, LogLevel } from '@roasmax/logger'
import type { LogHandler, LogEntry } from '@roasmax/logger'
import { LoggingConfig } from '../../shared/types'
import { DEFAULT_APP_CONFIG } from '../../shared/constants'
import * as fs from 'fs'
import * as path from 'path'

/**
 * 控制台日志处理器
 */
class ConsoleHandler implements LogHandler {
  constructor(private enableColors: boolean = true) { }

  handle(entry: LogEntry): void {
    const timestamp = new Date().toISOString()
    const levelName = LogLevel[entry.level]
    const prefix = `[${timestamp}] [${levelName}] [${entry.loggerName}]`

    // 确保消息是字符串格式
    const messageStr = this.formatMessage(entry.message)
    const argsStr = entry.args.map(arg => this.formatMessage(arg)).join(' ')

    const fullMessage = this.enableColors
      ? this.colorizeMessage(prefix, messageStr, entry.level)
      : `${prefix} ${messageStr}`

    const logOutput = argsStr ? `${fullMessage} ${argsStr}` : fullMessage

    switch (entry.level) {
      case LogLevel.ERROR:
        console.error(logOutput)
        break
      case LogLevel.WARN:
        console.warn(logOutput)
        break
      case LogLevel.INFO:
        console.info(logOutput)
        break
      case LogLevel.DEBUG:
        console.debug(logOutput)
        break
      default:
        console.log(logOutput)
    }
  }

  private formatMessage(msg: any): string {
    if (typeof msg === 'string') {
      return msg
    }
    if (msg === null || msg === undefined) {
      return String(msg)
    }
    if (typeof msg === 'object') {
      try {
        return JSON.stringify(msg, null, 2)
      } catch (error) {
        return String(msg)
      }
    }
    return String(msg)
  }

  private colorizeMessage(prefix: string, message: string, level: LogLevel): string {
    const colors = {
      [LogLevel.ERROR]: '\x1b[31m',   // 红色
      [LogLevel.WARN]: '\x1b[33m',    // 黄色
      [LogLevel.INFO]: '\x1b[36m',    // 青色
      [LogLevel.DEBUG]: '\x1b[37m'    // 白色
    }

    const reset = '\x1b[0m'
    const color = colors[level] || ''

    return `${color}${prefix}${reset} ${message}`
  }
}

/**
 * 文件日志处理器
 */
class FileHandler implements LogHandler {
  private logPath: string
  private maxFileSize: number
  private maxFiles: number

  constructor(config: { logPath: string; maxFileSize: number; maxFiles: number }) {
    this.logPath = config.logPath
    this.maxFileSize = config.maxFileSize
    this.maxFiles = config.maxFiles

    this.ensureLogDirectory()
  }

  handle(entry: LogEntry): void {
    const timestamp = new Date().toISOString()
    const levelName = LogLevel[entry.level]
    const logLine = `[${timestamp}] [${levelName}] [${entry.loggerName}] ${entry.message}\n`

    try {
      this.writeToFile(logLine)
    } catch (error) {
      console.error('Failed to write to log file:', error)
    }
  }

  private writeToFile(logLine: string): void {
    const logFile = path.join(this.logPath, 'app.log')

    // 检查文件大小，如果超过限制则轮转
    if (fs.existsSync(logFile)) {
      const stats = fs.statSync(logFile)
      if (stats.size > this.maxFileSize) {
        this.rotateLogFiles()
      }
    }

    fs.appendFileSync(logFile, logLine, 'utf8')
  }

  private rotateLogFiles(): void {
    const logFile = path.join(this.logPath, 'app.log')

    // 删除最旧的日志文件
    const oldestFile = path.join(this.logPath, `app.log.${this.maxFiles}`)
    if (fs.existsSync(oldestFile)) {
      fs.unlinkSync(oldestFile)
    }

    // 重命名现有的日志文件
    for (let i = this.maxFiles - 1; i >= 1; i--) {
      const currentFile = path.join(this.logPath, `app.log.${i}`)
      const nextFile = path.join(this.logPath, `app.log.${i + 1}`)

      if (fs.existsSync(currentFile)) {
        fs.renameSync(currentFile, nextFile)
      }
    }

    // 重命名当前日志文件
    if (fs.existsSync(logFile)) {
      const firstBackup = path.join(this.logPath, 'app.log.1')
      fs.renameSync(logFile, firstBackup)
    }
  }

  private ensureLogDirectory(): void {
    if (!fs.existsSync(this.logPath)) {
      fs.mkdirSync(this.logPath, { recursive: true })
    }
  }
}

/**
 * 日志服务
 */
export class LoggerService {
  private config: LoggingConfig
  private isInitialized = false

  constructor(config?: Partial<LoggingConfig>) {
    this.config = {
      ...DEFAULT_APP_CONFIG.logging,
      ...config
    }
  }

  /**
   * 初始化日志服务
   */
  async initialize(): Promise<void> {
    if (this.isInitialized) {
      return
    }

    try {
      // 设置日志级别
      const logLevel = this.mapLogLevel(this.config.level)
      Logger.setLevel(logLevel)

      // 添加控制台处理器
      Logger.addHandler(new ConsoleHandler())

      // 添加文件处理器
      if (this.config.enableFile !== false && this.config.logPath) {
        const maxFileSize = this.parseFileSize(this.config.maxSize)
        Logger.addHandler(new FileHandler({
          logPath: this.config.logPath,
          maxFileSize,
          maxFiles: this.config.maxFiles
        }))
      }

      this.isInitialized = true
      logger.info('Logger service initialized')

    } catch (error) {
      console.error('Failed to initialize logger service:', error)
      throw error
    }
  }

  /**
   * 更新日志配置
   */
  updateConfig(config: Partial<LoggingConfig>): void {
    this.config = { ...this.config, ...config }

    if (this.isInitialized) {
      // 重新初始化日志服务
      Logger.clearHandlers()
      this.isInitialized = false
      this.initialize()
    }
  }

  /**
   * 获取当前配置
   */
  getConfig(): LoggingConfig {
    return { ...this.config }
  }

  /**
   * 记录调试信息
   */
  debug(message: string, ...args: any[]): void {
    logger.debug(message, ...args)
  }

  /**
   * 记录信息
   */
  info(message: string, ...args: any[]): void {
    logger.info(message, ...args)
  }

  /**
   * 记录警告
   */
  warn(message: string, ...args: any[]): void {
    logger.warn(message, ...args)
  }

  /**
   * 记录错误
   */
  error(message: string, ...args: any[]): void {
    logger.error(message, ...args)
  }

  /**
   * 创建子日志器
   */
  createChildLogger(name: string): typeof logger {
    return createLogger(name)
  }

  /**
   * 清理日志文件
   */
  async cleanupLogs(retentionDays: number = 30): Promise<void> {
    if (!this.config.logPath) {
      return
    }

    try {
      const files = fs.readdirSync(this.config.logPath)
      const cutoffTime = Date.now() - (retentionDays * 24 * 60 * 60 * 1000)

      for (const file of files) {
        if (file.startsWith('app.log')) {
          const filePath = path.join(this.config.logPath, file)
          const stats = fs.statSync(filePath)

          if (stats.mtime.getTime() < cutoffTime) {
            fs.unlinkSync(filePath)
            logger.info(`Deleted old log file: ${file}`)
          }
        }
      }
    } catch (error) {
      logger.error('Failed to cleanup log files:', error)
    }
  }

  /**
   * 获取日志文件列表
   */
  getLogFiles(): string[] {
    if (!this.config.logPath || !fs.existsSync(this.config.logPath)) {
      return []
    }

    try {
      return fs.readdirSync(this.config.logPath)
        .filter(file => file.startsWith('app.log'))
        .sort()
    } catch (error) {
      logger.error('Failed to get log files:', error)
      return []
    }
  }

  /**
   * 映射日志级别
   */
  private mapLogLevel(level: string): LogLevel {
    const levelMap: Record<string, LogLevel> = {
      'debug': LogLevel.DEBUG,
      'info': LogLevel.INFO,
      'warn': LogLevel.WARN,
      'error': LogLevel.ERROR
    }

    return levelMap[level.toLowerCase()] || LogLevel.INFO
  }

  /**
   * 解析文件大小字符串
   */
  private parseFileSize(sizeStr: string): number {
    const match = sizeStr.match(/^(\d+)([kmg]?)b?$/i)
    if (!match) {
      return 10 * 1024 * 1024 // 默认10MB
    }

    const size = parseInt(match[1]!)
    const unit = match[2]!.toLowerCase()

    switch (unit) {
      case 'k':
        return size * 1024
      case 'm':
        return size * 1024 * 1024
      case 'g':
        return size * 1024 * 1024 * 1024
      default:
        return size
    }
  }
}
